/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup Camera
 * @{
 *
 * @brief Camera模块接口定义。
 *
 * camera模块涉及相机设备的操作、流的操作、离线流的操作和各种回调等。
 *
 * @since 1.0
 */

/**
 * @file istream_operator.h
 *
 * @brief 流的操作接口。
 *
 * @since 1.0
 * @version 1.0
 */

#ifndef HDI_STREAM_OPERATOR_CLIENT_INF_H
#define HDI_STREAM_OPERATOR_CLIENT_INF_H

#include <list>
#include <map>
#include <vector>
#include "istream_operator_callback.h"
#include "ioffline_stream_operator.h"
#include "types.h"
#include "icamera_interface.h"

namespace OHOS::Camera {
class IBufferProducer;
class IStreamOperator : public ICameraInterface {
public:
    /**
     * @brief IPC通信Token校验。
     * @since 1.0
     * @version 1.0
     */
    DECLARE_INTERFACE_DESCRIPTOR(u"HDI.Camera.V1_0.StreamOperator");

    virtual ~IStreamOperator() {}

    /**
     * @brief 查询是否支持添加参数对应的流
     *
     * 流是指从底层设备输出，经本模块内部各环节处理，最终传递到上层服务或者应用的一组数据序列
     * 本模块支持的流的类型有预览流，录像流，拍照流等，更多类型可查看 {@link StreamIntent}。
     *
     * 此函数接口根据输入的运行模式和配置信息以及当前模块中正在运行的流，查询是否支持动态添加流。
     * 如果本模块支持在不停止其他流的情况下添加新流，或者即使停止其他流但上层服务或应用不感知
     * 则通过type参数返回DYNAMIC_SUPPORTED，上层服务或应用可以直接添加新流；
     * 如果本模块支持添加新流但需要上层服务或应用先停止所有流的捕获，则通过type参数返回RE_CONFIGURED_REQUIRED;
     * 如果不支持添加输入的新流，则返回NOT_SUPPORTED。
     * 此函数需要在调用 {@link CreateStreams} 创建流之前调用。
     *
     * @param mode [IN] 流运行的模式，支持的模式参考 {@link OperationMode}。
     * @param modeSetting [IN] 流的配置，包括帧率，3A等配置信息。
     * @param info [IN] 流的配置信息，具体参考 {@link StreamInfo}。
     * @param type [OUT] 对动态配置流的支持类型，支持类型定义在 {@link StreamSupportType}。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode IsStreamsSupported(
        OperationMode mode,
        const std::shared_ptr<CameraMetadata> &modeSetting,
        const std::vector<std::shared_ptr<StreamInfo>> &info,
        StreamSupportType &type) = 0;

    /**
     * @brief 创建流。
     *
     * 此函数接口依据输入的流信息创建流，调用该接口之前需先通过 {@link IsStreamsSupported} 查询HAL是否支持要创建的流。
     *
     * @param streamInfos [IN] 流信息列表，流信息定义在 {@link StreamInfo}。输入的流信息可能会被修改，需通过
     * {@link GetStreamAttributes} 获取最新的流属性。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode CreateStreams(const std::vector<std::shared_ptr<StreamInfo>> &streamInfos) = 0;

    /**
     * @brief 释放流。
     *
     * @param streamIds [IN] 要释放的流ID列表。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode ReleaseStreams(const std::vector<int> &streamIds) = 0;

    /**
     * @brief 配置流。
     *
     * 本接口需在调用 {@link CreateStreams} 创建流之后调用。
     *
     * @param mode [IN] 流运行的模式，支持的模式定义在 {@link OperationMode}。
     * @param modeSetting [IN] 流的配置参数，包括帧率，ZOOM等信息。
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode CommitStreams(OperationMode mode,
        const std::shared_ptr<CameraMetadata> &modeSetting) = 0;

    /**
     * @brief 获取流的属性。
     *
     * @param attributes [OUT] 用于获取流的属性。在调用{@link CreateStreams} 时，通过参数streamInfos携带的流信息
     * 可能会被重写，因此通过该接口获取的流属性可能会。
	 * 和 {@link CreateStreams} 输入的流信息存在差异。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode GetStreamAttributes(
        std::vector<std::shared_ptr<StreamAttribute>> &attributes) = 0;

    /**
     * @brief 绑定生产者句柄和指定流。
     *
     * 如果在 {@link CreateStreams} 创建流时已经指定了生产者句柄，则不需要调用该接口。如果需要重新绑定，
     * 需先调用 {@link DetachBufferQueue} 进行解绑，然后再绑定。
     * 对于一些IOT设备，可能不需要或者不支持预览流的图像数据缓存流转，那么不需要绑定生产者句柄，
     * 此时在创建流时 {@link CreateStreams} 的 {@link StreamInfo} 参数的生产者句柄bufferQueue_为空，而
     * tunneledMode_需设置为false。
     *
     * @param streamId [IN] 用于标识要绑定的流。
     * @param producer [IN] 生产者句柄。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @see DetachBufferQueue
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr<OHOS::IBufferProducer> &producer) = 0;

    /**
     * @brief 解除生产者句柄和指定流的绑定关系。
     *
     * @param streamId [IN] 用于标识要解除绑定的流。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @see AttachBufferQueue
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode DetachBufferQueue(int streamId) = 0;

    /**
     * @brief 捕获图像。
     *
     * 本接口必须在调用 {@link CommitStreams} 配置流之后调用。
     * 图像捕获有两种模式，分别是连续捕获和单次捕获。连续捕获即触发之后模块内部进行连续的捕获，
     * 消费者可以连续收到图像数据，不需要多次调用本接口，若再次调用了本接口，
     * 则停止当前捕获，更新捕获信息，再进行一次新的捕获，多用于预览、录像或者连拍场景。
     * 单次捕获即触发之后只捕获一帧图像数据，用于单次拍照场景。\n
     * 捕获启动时，会调用 {@link OnCaptureStarted} 来通知调用者捕获已经启动。
     * 连续捕获需调用 {@link CancelCapture} 来停止捕获。
     * 捕获结束时，会调用 {@link OnCaptureEnded} 来通知调用者捕获的帧计数等信息。
     * {@link CaptureInfo} 的 enableShutterCallback_ 使能 {@link OnFrameShutter}，使能后每次捕获触发 {@link OnFrameShutter}
     * 对于多个流同时捕获的场景，本模块内部保证同时上报多路流捕获数据。
     *
     * @param captureId [IN] 捕获请求的唯一标识，由调用者指定，调用者需保证在Camera设备打开期间，捕获请求ID是唯一的。
     * @param info [IN] 捕获请求的参数信息，具体信息查看 {@link CaptureInfo}。
     * @param isStreaming [IN] 是否连续捕获，true表示连续捕获，否则为单次捕获。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @see OnFrameShutter
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode Capture(int captureId,
        const std::shared_ptr<CaptureInfo> &info,  bool isStreaming) = 0;

    /**
     * @brief 取消捕获。
     *
     * 取消连续捕获时会调用 {@link OnCaptureEnded}。
     *
     * @param captureId 用于标识要取消的捕获请求
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @see Capture
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode CancelCapture(int captureId) = 0;

    /**
     * @brief 将指定流转换成离线流。
     *
     * 离线流只能由拍照流转换而来，其他流不支持。
     * 一些设备处理能力有限，可能导致拍照时算法处理时间较长，从而引起捕获请求堆积在模块内部，而转换为离线
     * 流之后，可关闭底层设备，由离线流接替，进行后续的处理。
     *
     * @param streamIds [IN] 用于指定要转换成离线流的流集合。
     * @param callback [IN] 用于设置离线流的回调。
     * @param offlineOperator [OUT] 转换后的离线流。
     *
     * @return Returns NO_ERROR 表示执行成功；
     * @return Returns 其他值表示执行失败，具体错误码查看 {@link CamRetCode}。
     *
     * @since 1.0
     * @version 1.0
     */
    virtual CamRetCode ChangeToOfflineStream(const std::vector<int> &streamIds,
        OHOS::sptr<IStreamOperatorCallback> &callback,
        OHOS::sptr<IOfflineStreamOperator> &offlineOperator) = 0;
};
}

#endif /** HDI_STREAM_OPERATOR_CLIENT_INF_H